from loggers import * 
from random import randint
from datetime import datetime 

lj_host = 'www.livejournal.com'

PORT = 80
TIMEOUT_SECONDS = 20
MAX_ATTEMPTS = 5

class LjClient(type):

    def __init__(self, user, password, logger_class=None):        
        self.user, self.password, self.debug_mode = user, password, debug_mode        
        self.logger = logger_class() or fake_logger()
        self.name = ''        
        self.login()        

    def get_friends(self):        
        self.logger.request('Getting friends...')        
        response = self._request(
            mode='getfriends',
        )        
        self.logger.response('Friends: %s' % response)
        return response

    def delete_friend(self, username):
        self.logger.request('Delete: %s' % username)        
        params = {                
            'mode': 'editfriends',
            'editfriend_delete_%s' % username: 1,
        }
        response = self._request(**params)
        self.logger.response('Done: %s' % response)

    def add_friend(self, username):
        self.logger.request('Adding: %s' % username)
        any_unique_integer = randint(1,25000)
        params = {                
            'mode': 'editfriends',
            'editfriend_add_%d_user' % any_unique_integer: username,
        }
        response = self._request(**params)
        self.logger.response('Done: %s' % response)

    def post(self, text, subj='',):
        self.logger.request('Posting...')        
        dt = datetime.today() 
        params = {
            'mode': 'postevent',
            'event': text.replace('\r', ''),
            'lineendings': 'unix',  # 'unix', 'pc', 'mac'
            'subject': subj,
            'year': dt.year,
            'mon':  u'%02d' % dt.month,
            'day':  dt.day,
            'hour': dt.hour,
            'min':  u'%02d' % dt.minute,
        }
        security_params = { 'security': 'public' }
        #security_params = { 'security': 'private' }
        #security_params = { 'security': 'usemask', 'allowmask': mask }
        params.update(security_params)        
        response = self._request(**params)
        self.logger.response('Done: %s' % response)

    def login(self):
        self.logger.request('Login as %s' % self.user)
        response = self._request(
            mode='login',
        )
##        unset($hResponse['access']['count']);
##        $this->arrAccess = array_values($hResponse['access']);
        self.name = response['name']
        self.logger.response('Welcome, %s' % self.name)    

#    private function checkResponseOk(array $hResponse) {
#        if ($hResponse['success'] != 'OK')
#            throw new Exception('Failed:' . print_r($hResponse, 1));
#    }
#
    def _get_login_params(self):
        return {
            'user': self.user,
            'auth_method': 'clear',  # deprecated. TODO make better
            'hpassword': md5(self.password),
            'ver': 1,
        }
        
    def _convetFlatResponseToHash(self, response):        
        result = {}        
        response.reverse()
        while len(response) > 1:
            key, val = response.pop(), response.pop() 
            key_parts = key.split('_')                          
            pointer = result                      
            for i, k in enumerate(key_parts):                
                is_last = (i == (len(key_parts) - 1))
                if is_last:
                    pointer[k] = val
                else:
                    if not k in pointer:
                        pointer[k] = {}
                        pointer = pointer[k]                                                    
        return result

    def _request(self, **kwargs) {
        params = self._get_login_params()
        params.update(kwargs)
#        kwargs
#        $connect = new SocketConnect(self::lj_host, self::PORT, self::TIMEOUT_SECONDS);
#
#        $content = SocketConnect::composeData($hFields);
#
#        if ($isDebug) {
#            echo $content;
#            return array();
#        }
#
#        $connect->addLine('POST /interface/flat HTTP/1.0');
#        $connect->addLine('Host: ' . self::lj_host);
#        $connect->addLine('Content-type: application/x-www-form-urlencoded');
#        $connect->addLine('Content-length: ' . strlen($content));
#        $connect->addSeparator();
#        $connect->addLine($content);
#
#        $response = $connect->send();
#
#        $this->arrCookies = $response->getCookies();
#
#        $hResponse = $this->convetFlatResponseToHash($response->getContentAsLinesArray());
#
#        if (empty($hResponse))
#            throw new Exception('Empty response');
#
#        $this->checkResponseOk($hResponse);
#
#        return $hResponse;
#    }


class LjPost {

    private $subj = '';
    public function setSubj($str) { $this->subj = strtr($str, array("\r" => '', "\n" => '')); }
    public function getSubj() { return $this->subj; }

    private $text = '';
    public function setText($str) { $this->text = strtr($str, array("\r" => '')); }
    public function getText() { return $this->text; }

    private $time = 0;
    public function setDate(Date $oDate = null) { $this->time = $oDate ? $oDate->getTimestamp() : time(); }
    //public function getTime() { return $this->time; }
    public function getYear() { return date('Y', $this->time); }
    public function getMon() { return date('n', $this->time); }
    public function getDay() { return date('j', $this->time); }
    public function getHour() { return date('G', $this->time); }
    public function getMin() { return date('i', $this->time); }

    private $security = '';
    private $allowmask = 0;
    public function setSecurityPublic() { $this->security = 'public'; }
    public function setSecurityPrivate() { $this->security = 'private'; }
    public function setSecurityMask($mask) {
        $this->security = 'usemask';
        $this->allowmask = $mask;
    }
    public function getSecurity() { return $this->security; }
    public function getAllowmask() { return $this->allowmask; }


    public function getLineEndings() { return 'unix'; } // unix, pc, mac

    public function checkIsCorrect() {

        if (!$this->getText())
          throw new Exception('Text cannot be emty!');

        return true;
    }
}
